/**********
Copyright 1990 Regents of the University of California.  All rights reserved.
Author: 1985 Wayne A. Christopher
**********/

/*
 * The main routine for spice 3 and nutmeg.
 */

#include "../log.h"
#include <android/log.h>
#include <string.h>

#include "spice.h"
#include "misc.h"
#include "ifsim.h"
#include "inpdefs.h"
#include "iferrmsg.h"
#include "cpdefs.h"
#include "ftedefs.h"
#include "ftedev.h"
#include "ftedebug.h"
#include "const.h"
#include <setjmp.h>

#include <sys/types.h>

#include "vspice.h"

#ifdef HAS_GETPW
#include <pwd.h>
#endif

#ifndef HAS_BSDRUSAGE
#ifdef HAS_FTIME
#include <sys/timeb.h>
#endif
#endif

#include "patchlev.h"
#include "suffix.h"

struct plot *pl = NULL;
struct dvec *vec = NULL;

int Patch_Level = PATCHLEVEL;
char *ft_rawfile = "rawspice.raw";

char *errRtn;
char *errMsg;
char *cp_program;

bool ft_servermode = false;
bool ft_intrpt = false;     /* Set by the (void) signal handlers. */
bool ft_setflag = false;    /* Don't abort after an interrupt. */

struct variable *(*if_getparam)( );

#ifdef BATCH

#else

bool ft_batchmode = false;
jmp_buf jbuf;
static char *usage = 
"Usage: %s [-] [-b] [-i] [-s] [-n] [-o outfile] [-r rawfile]\n\
\t[-t term] [file ...]\n";
struct options *exitoption;
struct options *helpoption;
#endif

static started = false;
IFsimulator *ft_sim = 0;

#ifndef HAS_BSDRUSAGE
#ifdef HAS_FTIME
extern struct timeb timebegin;		/* for use w/ ftime */
#endif
#endif

extern IFsimulator SIMinfo;

#ifdef SIMULATOR

bool ft_nutmeg = false;

#ifndef BATCH
extern struct comm spcp_coms[ ];
struct comm *cp_coms = spcp_coms;
#endif
extern int OUTpBeginPlot(), OUTpData(), OUTwBeginPlot(), OUTwReference();
extern int OUTwData(), OUTwEnd(), OUTendPlot(), OUTbeginDomain();
extern int OUTendDomain(), OUTstopnow(), OUTerror(), OUTattributes();
static IFfrontEnd nutmeginfo = {
    IFnewUid,
    IFdelUid,
    OUTstopnow,
    seconds,
    OUTerror,
    OUTpBeginPlot,
    OUTpData,
    OUTwBeginPlot,
    OUTwReference,
    OUTwData,
    OUTwEnd,
    OUTendPlot,
    OUTbeginDomain,
    OUTendDomain,
    OUTattributes
};

#else

#endif

char *hlp_filelist[] = { "spice", 0 };

int spice(const char *cirname, const char *rawname) 
{
    int		i;
    int		err;
    bool	gotone = false;
    char	*p;
    char	*cmd_line_term = 0, term_1stch;
    int		error2;

#ifdef BATCH
    bool	st = false;
#else

#ifdef HAS_GETPW
    struct passwd *pw;
#endif
    char	buf[BSIZE_SP];
    bool	readinit = true, rflag = false, ciprefix();
    bool	istty = true, iflag = false, qflag = false;
    bool	gdata = true;
    FILE	*fp;

#endif

    started = true;

    cp_in = stdin;
    cp_out = stdout;
    cp_err = stderr;

#ifdef HAS_ISATTY
    istty = (bool) isatty(fileno(stdin));
#endif

    init_time( );

    err = SIMinit(&nutmeginfo,&ft_sim);
    if(err != OK) {
        ft_sperror(err,"SIMinit");
		return -1;
    }
    cp_program = ft_sim->simulator;

#ifdef HAS_GETPID
    srandom(getpid());
#else
    srandom(17);
#endif
    /* Pass 1 -- get options. */
	ft_batchmode = true;

#ifndef BATCH
	
	//cp_vset("rawfile", VT_STRING, "/sdcard/vspice/rc.raw");
	cp_vset("rawfile", VT_STRING, rawname);
	rflag = true;

#else /* if BATCH */
#endif

#ifdef SIMULATOR
    if_getparam = spif_getparam;
	LOG("spif_getparam\n");
#endif

#ifndef BATCH
	LOG("BATCH is not defined\n");
    if ((!iflag && !istty) || ft_servermode)
        ft_batchmode = true;
    if ((iflag && !istty) || qflag)
        cp_nocc = true;
    if (!istty || ft_batchmode)
        out_moremode = false;

    /* Would like to do this later, but cpinit evals commands */
    init_rlimits( );

    /* Have to initialize cp now. */
	LOG("before ft_cpinit()\n");
    ft_cpinit();
	LOG("after ft_cpinit()\n");

    /* To catch interrupts during .spiceinit... */
    if (setjmp(jbuf) == 1) {
        LOG("Warning: error executing .spiceinit.\n");
        if (!ft_batchmode)
            goto bot;
    }

#  ifdef HAS_GETPW
    if (readinit) {
        /* Try to source either .spiceinit or ~/.spiceinit. */
        if (access(".spiceinit", 0) == 0)
            inp_source(".spiceinit");
        else {
            pw = getpwuid(getuid());
            (void) strcpy(buf, pw->pw_dir);
            (void) strcat(buf, "/.spiceinit");
            if (access(buf, 0) == 0)
                inp_source(buf);
        }
    }
#  else /* ~ HAS_GETPW */
    /* Try to source the file "spice.rc" in the current directory.  */
    if (readinit) {
        if ((fp = fopen("spice.rc", "r")) != NULL) {
            (void) fclose(fp);
            inp_source("spice.rc");
        }
    }
#  endif /* ~ HAS_GETPW */

    if (cmd_line_term) {
	*cmd_line_term = term_1stch; /* XXX oh, gross!
				      *	First char got squashed scanning the
				      * command line
				      */
	cp_vset("term", VT_STRING, cmd_line_term);
    }

bot:

    /* Pass 2 -- get the filenames. If we are spice, then this means
     * build a circuit for this file. If this is in server mode, don't
     * process any of these args.
     */

#endif /* ~ BATCH */

    cp_interactive = false;
    err = 0;

#ifdef SIMULATOR
	LOG("simul...\n");

	FILE *file = NULL, *tp = NULL;
	char *tempfile = NULL, *smktemp();

	if (!(file = fopen(cirname, "r"))) {
		if (ft_batchmode)
			return -1;
	}
	LOG("file && (!err || !ft_Batchmode)\n");
	inp_spsource(file, false, cirname);
	gotone = true;

#  ifndef BATCH
evl:
	/* If we get back here in batch mode then something is
	 * wrong, so exit.
	 */
	(void) setjmp(jbuf);

	/* If -r is specified, then we don't bother with the dot
	 * cards. Otherwise, we use wrd_run, but we are careful
	 * not to save too much.
	 */
	cp_interactive = false;
	if (rflag) {
		ft_dotsaves();
		error2 = ft_dorun(ft_rawfile);
		if (ft_cktcoms(true) || error2)
			return -1;
	} else {
		if (ft_savedotargs()) {
			LOG("ft_dorun(NULL); \n");
			error2 = ft_dorun(NULL);
			if (ft_cktcoms(false) || error2)
				return -1;
		} else {
			LOG("Note: No \".plot\", \".print\", or \".fourier\" lines; no simulations run\n");
			return -1;
		}
	}

#  else /* if BATCH */

#  endif
#endif
	LOG("simulation ends");
	return 0;
}

/* allocate space for global constants in 'CONST.h' */

double CONSTroot2;
double CONSTvt0;
double CONSTKoverQ;
double CONSTe;
IFfrontEnd *SPfrontEnd = NULL;

int
SPIinit(frtEnd,description)
    IFfrontEnd *frtEnd;
    IFsimulator **description;
{

    SPfrontEnd = frtEnd;
    *description = &SIMinfo;
    CONSTroot2 = sqrt(2.);
    CONSTvt0 = CONSTboltz * (27 /* deg c */ + CONSTCtoK ) / CHARGE;
    CONSTKoverQ = CONSTboltz / CHARGE;
    CONSTe = exp((double)1.0);
    return(OK);
}

/* XXX SIMinit and SPIinit ?? */

int SIMinit(frontEnd,simulator)
    IFfrontEnd *frontEnd;
    IFsimulator **simulator;
{
    return(SPIinit(frontEnd,simulator));
}

void readdata_fromraw(const char *name)
{
	char buf[80];
	int i;

	if(pl)
		free(pl);
	pl = raw_read(name);
	if(vec)
		free(vec);
	vec = pl->pl_dvecs;

	for(i = 0 ; i < vec->v_length ; i++) {
		sprintf(buf, "%.2lf\n", vec->v_realdata[i]);
		LOG(buf);
	}
}

int get_realdata(char *name, double **data, int *n)
{
	struct dvec *tvec;

	if(!vec)
		return 0;

	for(tvec = vec ; tvec != NULL ; tvec = tvec->v_next) {
		if(!strncmp(tvec->v_name, name, strlen(name))) {
			*n = tvec->v_length;
			*data = (tvec->v_realdata);
		}
	}

	return 1;
}

int get_dataname()
{
	struct dvec *tvec;
	char **name;
	if(!vec)
		return 0;

	for(tvec = vec ; tvec != NULL ; tvec = tvec->v_next) {

	}
}

int get_numdata()
{
	return vec->v_length;
}

char **get_varname(int *size) 
{
	struct dvec *tvec;
	char **name;
	if(!vec)
		return NULL;

	int num = 0;
	for(tvec = vec ; tvec != NULL ; tvec = tvec->v_next) {
		num++;
	}

	name = (char **)malloc(sizeof(char *) * num);
	num = 0;
	for(tvec = vec ; tvec != NULL ; tvec = tvec->v_next) {
		name[num++] = tvec->v_name;
	}

	return name;
}
